using UnityEngine;
using System.Collections;

[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
public class DynamicMeshGenerator : MonoBehaviour
{
    [Header("网格设置")]
    [SerializeField] private int width = 40;
    [SerializeField] private int height = 20;
    [SerializeField] private float cellSize = 1f;
    
    [Header("动态更新设置")]
    [SerializeField] private bool enableDynamicUpdate = true;
    [SerializeField] private float updateInterval = 0.5f; // 更新间隔（秒）
    [SerializeField] private int minHeight = 0;
    [SerializeField] private int maxHeight = 5;
    [SerializeField] private float lerpSpeed = 2.0f; // 插值速度
    
    [Header("压力传递设置")]
    [SerializeField] private float pressureAttenuation = 0.7f; // 压力衰减系数（0-1之间，值越小衰减越快）
    [SerializeField] private bool enablePressurePropagation = true; // 是否启用压力传递
    
    [Header("材质设置")]
    [SerializeField] private Material meshMaterial;
    
    [Header("Y轴偏移数据")]
    [SerializeField] private int[] yOffsetData = new int[40];
    
    private Mesh mesh;
    private Vector3[] vertices;
    private int[] triangles;
    private Vector2[] uv;
    
    // 用于插值的变量
    private float[] currentYOffsets; // 当前显示的Y偏移值（浮点数，用于平滑过渡）
    private float[] targetYOffsets; // 目标Y偏移值（从yOffsetData转换而来）
    
    private void Awake()
    {
        // 初始化Y轴偏移数据（示例数据）
        InitializeYOffsetData();
        
        // 初始化插值相关变量
        InitializeInterpolationVariables();
        
        // 创建网格
        GenerateMesh();
        
        // 启动动态更新协程
        if (enableDynamicUpdate)
        {
            StartCoroutine(DynamicUpdateRoutine());
        }
    }
    
    private void InitializeYOffsetData()
    {
        // 如果没有设置Y轴偏移数据，则使用随机数据初始化
        if (yOffsetData == null || yOffsetData.Length != width)
        {
            yOffsetData = new int[width];
            for (int i = 0; i < width; i++)
            {
                yOffsetData[i] = Random.Range(minHeight, maxHeight + 1);
            }
        }
    }
    
    private void InitializeInterpolationVariables()
    {
        // 初始化当前和目标Y偏移数组
        currentYOffsets = new float[width];
        targetYOffsets = new float[width];
        
        // 初始值设置为yOffsetData的值
        for (int i = 0; i < width; i++)
        {
            currentYOffsets[i] = yOffsetData[i] * cellSize;
            targetYOffsets[i] = yOffsetData[i] * cellSize;
        }
    }
    
    // 动态更新协程
    private IEnumerator DynamicUpdateRoutine()
    {
        while (enableDynamicUpdate)
        {
            // 等待指定的时间间隔
            yield return new WaitForSeconds(updateInterval);
        }
    }
    
    // 在Update中实时更新顶点位置（使用插值）
    private void Update()
    {
        if (!enableDynamicUpdate) return;
        
        bool hasChanged = false;
        
        // 对每个顶点进行插值更新
        for (int i = 0; i < currentYOffsets.Length; i++)
        {
            // 使用Lerp进行平滑过渡
            float newYOffset = Mathf.Lerp(currentYOffsets[i], targetYOffsets[i], Time.deltaTime * lerpSpeed);
            
            // 如果变化超过阈值，则标记需要更新
            if (Mathf.Abs(newYOffset - currentYOffsets[i]) > 0.001f)
            {
                currentYOffsets[i] = newYOffset;
                hasChanged = true;
            }
        }
        
        // 如果有变化，则更新网格
        if (hasChanged)
        {
            UpdateMeshFromCurrentYOffsets();
        }
    }
    
    public void GenerateMesh()
    {
        // 获取或创建Mesh组件
        MeshFilter meshFilter = GetComponent<MeshFilter>();
        if (meshFilter == null)
        {
            meshFilter = gameObject.AddComponent<MeshFilter>();
        }
        
        // 获取或创建MeshRenderer组件
        MeshRenderer meshRenderer = GetComponent<MeshRenderer>();
        if (meshRenderer == null)
        {
            meshRenderer = gameObject.AddComponent<MeshRenderer>();
        }
        
        // 创建新的Mesh
        mesh = new Mesh();
        mesh.name = "DynamicMesh";
        
        // 生成顶点、三角形和UV
        CreateVertices();
        CreateTriangles();
        CreateUV();
        
        // 将数据赋值给Mesh
        mesh.vertices = vertices;
        mesh.triangles = triangles;
        mesh.uv = uv;
        
        // 重新计算法线和边界
        mesh.RecalculateNormals();
        mesh.RecalculateBounds();
        
        // 将Mesh赋值给MeshFilter
        meshFilter.mesh = mesh;
        
        // 设置材质
        if (meshMaterial != null)
        {
            meshRenderer.material = meshMaterial;
        }
        else if (meshRenderer.material == null)
        {
            // 如果没有设置材质且MeshRenderer没有材质，则创建默认材质
            meshRenderer.material = new Material(Shader.Find("Standard"));
        }
    }
    
    private void CreateVertices()
    {
        // 顶点数量：(width + 1) * (height + 1)
        vertices = new Vector3[(width + 1) * (height + 1)];
        
        for (int y = 0; y <= height; y++)
        {
            for (int x = 0; x <= width; x++)
            {
                // 计算顶点索引
                int index = y * (width + 1) + x;
                
                // 计算顶点位置 - 现在在XY平面上
                float xPos = x * cellSize;
                float yPos = y * cellSize;
                float zPos = 0f;
                
                // 如果启用了压力传递，则根据高度数据计算每个顶点的Y值
                if (enablePressurePropagation)
                {
                    // 确保x在高度数据范围内
                    if (x < yOffsetData.Length)
                    {
                        // 计算当前层的高度影响系数（从上到下逐渐减小）
                        float heightFactor = Mathf.Pow(pressureAttenuation, height - y);
                        
                        // 顶点变化在Y轴方向，根据高度系数调整影响程度
                        yPos += yOffsetData[x] * cellSize * heightFactor;
                    }
                }
                else
                {
                    // 如果没有启用压力传递，则只有最上面的一行顶点会根据高度数据设置Y值
                    if (y == height)
                    {
                        // 确保x在高度数据范围内
                        if (x < yOffsetData.Length)
                        {
                            // 顶点变化在Y轴方向，所以这里增加yPos
                            yPos += yOffsetData[x] * cellSize;
                        }
                    }
                }
                
                vertices[index] = new Vector3(xPos, yPos, zPos);
            }
        }
    }
    
    private void CreateTriangles()
    {
        // 每个单元格有2个三角形，每个三角形有3个顶点
        triangles = new int[width * height * 6];
        
        int triangleIndex = 0;
        
        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                // 计算当前单元格四个顶点的索引
                int topLeft = y * (width + 1) + x;
                int topRight = topLeft + 1;
                int bottomLeft = (y + 1) * (width + 1) + x;
                int bottomRight = bottomLeft + 1;
                
                // 第一个三角形（左下、右下、左上）
                triangles[triangleIndex++] = bottomLeft;
                triangles[triangleIndex++] = bottomRight;
                triangles[triangleIndex++] = topLeft;
                
                // 第二个三角形（左上、右下、右上）
                triangles[triangleIndex++] = topLeft;
                triangles[triangleIndex++] = bottomRight;
                triangles[triangleIndex++] = topRight;
            }
        }
    }
    
    private void CreateUV()
    {
        // UV数量与顶点数量相同
        uv = new Vector2[vertices.Length];
        
        for (int y = 0; y <= height; y++)
        {
            for (int x = 0; x <= width; x++)
            {
                int index = y * (width + 1) + x;
                
                // 计算UV坐标（0-1范围）
                float u = (float)x / width;
                float v = (float)y / height;
                
                uv[index] = new Vector2(u, v);
            }
        }
    }
    
    // 根据当前Y轴偏移数据更新网格
    private void UpdateMeshFromYOffsetData()
    {
        // 更新目标偏移值
        for (int i = 0; i < yOffsetData.Length; i++)
        {
            targetYOffsets[i] = yOffsetData[i] * cellSize;
        }
        
        // 重新生成顶点
        CreateVertices();
        
        // 更新Mesh
        mesh.vertices = vertices;
        mesh.RecalculateNormals();
        mesh.RecalculateBounds();
        
        // 如果启用了压力传递，还需要更新当前偏移值
        if (enablePressurePropagation)
        {
            for (int i = 0; i < currentYOffsets.Length; i++)
            {
                currentYOffsets[i] = targetYOffsets[i];
            }
        }
    }
    
    // 根据当前插值后的Y偏移值更新网格
    private void UpdateMeshFromCurrentYOffsets()
    {
        // 更新顶点位置
        for (int y = 0; y <= height; y++)
        {
            for (int x = 0; x <= width; x++)
            {
                // 计算顶点索引
                int index = y * (width + 1) + x;
                
                // 计算顶点位置 - 现在在XY平面上
                float xPos = x * cellSize;
                float yPos = y * cellSize;
                float zPos = 0f;
                
                // 如果启用了压力传递，则根据高度数据计算每个顶点的Y值
                if (enablePressurePropagation)
                {
                    // 确保x在高度数据范围内
                    if (x < currentYOffsets.Length)
                    {
                        // 计算当前层的高度影响系数（从上到下逐渐减小）
                        float heightFactor = Mathf.Pow(pressureAttenuation, height - y);
                        
                        // 顶点变化在Y轴方向，根据高度系数调整影响程度
                        yPos += currentYOffsets[x] * heightFactor;
                    }
                }
                else
                {
                    // 如果没有启用压力传递，则只有最上面的一行顶点会根据高度数据设置Y值
                    if (y == height)
                    {
                        // 确保x在高度数据范围内
                        if (x < currentYOffsets.Length)
                        {
                            // 顶点变化在Y轴方向，所以这里增加yPos
                            yPos += currentYOffsets[x];
                        }
                    }
                }
                
                vertices[index] = new Vector3(xPos, yPos, zPos);
            }
        }
        
        // 更新Mesh
        mesh.vertices = vertices;
        mesh.RecalculateNormals();
        mesh.RecalculateBounds();
    }
    
    // 更新高度数据并重新生成网格
    public void UpdateYOffsetData(int[] newYOffsetData)
    {
        if (newYOffsetData == null || newYOffsetData.Length != width)
        {
            Debug.LogError($"Y轴偏移数据数组长度必须等于网格宽度。期望: {width}, 实际: {(newYOffsetData != null ? newYOffsetData.Length.ToString() : "null")}");
            return;
        }
        
        // 输出调试信息
        Debug.Log($"更新Y轴偏移数据 - 数据点数: {newYOffsetData.Length}, 最小值: {Mathf.Min(newYOffsetData)}, 最大值: {Mathf.Max(newYOffsetData)}");
        
        yOffsetData = newYOffsetData;
        
        // 只更新目标偏移值，让插值系统在Update中平滑过渡
        for (int i = 0; i < yOffsetData.Length; i++)
        {
            targetYOffsets[i] = yOffsetData[i] * cellSize;
        }
        
        // 不再直接更新网格，而是让Update方法中的插值系统平滑过渡
        // UpdateMeshFromYOffsetData();
    }
    
    // 设置单个顶点的Y轴偏移
    public void SetVertexYOffset(int index, int yOffset)
    {
        if (index < 0 || index >= width)
        {
            Debug.LogError("顶点索引超出范围");
            return;
        }
        
        yOffsetData[index] = yOffset;
        targetYOffsets[index] = yOffset * cellSize;
        
        // 更新网格
        UpdateMeshFromYOffsetData();
    }
    
    // 启动/停止动态更新
    public void SetDynamicUpdate(bool enable)
    {
        enableDynamicUpdate = enable;
        
        if (enable)
        {
            StartCoroutine(DynamicUpdateRoutine());
        }
        else
        {
            StopAllCoroutines();
        }
    }
    
    // 设置更新间隔
    public void SetUpdateInterval(float interval)
    {
        updateInterval = Mathf.Max(0.1f, interval); // 最小间隔0.1秒
    }
    
    // 获取当前Y轴偏移数据
    public int[] GetYOffsetData()
    {
        return yOffsetData;
    }
    
    // 设置网格材质
    public void SetMeshMaterial(Material material)
    {
        if (material == null)
        {
            Debug.LogWarning("设置的材质为空，将使用默认材质");
            return;
        }
        
        meshMaterial = material;
        
        // 获取MeshRenderer组件并更新材质
        MeshRenderer meshRenderer = GetComponent<MeshRenderer>();
        if (meshRenderer != null)
        {
            meshRenderer.material = meshMaterial;
        }
    }
    
    // 获取当前网格材质
    public Material GetMeshMaterial()
    {
        return meshMaterial;
    }
    
    // 设置压力衰减系数
    public void SetPressureAttenuation(float attenuation)
    {
        pressureAttenuation = Mathf.Clamp01(attenuation);
    }
    
    // 获取压力衰减系数
    public float GetPressureAttenuation()
    {
        return pressureAttenuation;
    }
    
    // 启用/禁用压力传递
    public void SetPressurePropagation(bool enable)
    {
        enablePressurePropagation = enable;
        // 如果改变了压力传递模式，需要重新生成网格
        UpdateMeshFromCurrentYOffsets();
    }
    
    // 获取压力传递是否启用
    public bool GetPressurePropagation()
    {
        return enablePressurePropagation;
    }
    
    // 在Unity编辑器中可视化网格
    private void OnDrawGizmos()
    {
        if (vertices == null) return;
        
        Gizmos.color = Color.yellow;
        
        // 绘制顶点
        for (int i = 0; i < vertices.Length; i++)
        {
            Gizmos.DrawSphere(transform.position + vertices[i], 0.05f);
        }
    }
}